package com.auxgroup.smarthome.inner.service;

import com.auxgroup.smarthome.BeanUtils;
import com.auxgroup.smarthome.inner.dto.AppVersionDto;
import com.auxgroup.smarthome.inner.dto.SearchAppVersionDto;
import com.auxgroup.smarthome.inner.entity.AppVersionEntity;
import com.auxgroup.smarthome.inner.repo.AppVersionRepo;
import com.auxgroup.smarthome.inner.vo.AppVersionVo;
import com.auxgroup.smarthome.syscode.Syscode;
import com.auxgroup.smarthome.utils.PageContent;
import com.auxgroup.smarthome.utils.PageUtils;
import com.auxgroup.smarthome.web.ApiResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.Predicate;
import javax.transaction.Transactional;
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

/**
 * app版本
 * Created by lixiaoxiao on 17-8-1.
 */
@Service
public class AppVersionService {

    @Autowired
    private AppVersionRepo appVersionRepo;

    public AppVersionVo findAppVersion() {
        AppVersionEntity appVersionEntity = appVersionRepo.findAppVersionEntity();
        AppVersionVo appVersionVo = BeanUtils.copyAttrs(new AppVersionVo(), appVersionEntity);
        return appVersionVo;
    }

    public PageContent<AppVersionVo> searchAppVersions(String keywords, String createTimeSlot, int page, int size) {
        page = page < 0 ? 0 : page;
        Pageable pageable = new PageRequest(page, size);
        SearchAppVersionDto searchAppVersionDto = new SearchAppVersionDto(keywords, createTimeSlot);
        Specification<AppVersionEntity> specification = where(searchAppVersionDto);
        Page<AppVersionEntity> all = appVersionRepo.findAll(specification, new PageRequest(pageable.getPageNumber(), pageable.getPageSize(), new Sort(Sort.Direction.DESC, "createdAt")));
        Page<AppVersionVo> appVersionVos = new PageUtils(AppVersionVo.class, all).buildVosPage();
        return new PageContent<AppVersionVo>(appVersionVos);
    }


    public ApiResponse createAppVersion(AppVersionDto appVersionDto) {
        Syscode comfirm = confirmData(appVersionDto);
        if (comfirm != null) return ApiResponse.prompt(comfirm);
        AppVersionEntity newEntity = appVersionDto.createAppVerion(appVersionDto);
        appVersionRepo.save(newEntity);
        return ApiResponse.ok(newEntity.getAppVersionId());
    }

    public ApiResponse updateAppVersion(String appVersionId, AppVersionDto appVersionDto) {
        Syscode comfirm = confirmData(appVersionDto);
        if (comfirm != null) return ApiResponse.prompt(comfirm);
        AppVersionEntity appVersionEntity = appVersionRepo.findOne(appVersionId);
        appVersionRepo.save(appVersionDto.updateAppVersion(appVersionEntity));
        return ApiResponse.prompt(Syscode.SC_OK);
    }


    @Transactional
    public ApiResponse deleteAppVersionById(String id) {
        AppVersionEntity appVersionEntity = appVersionRepo.findOne(id);
        if (appVersionEntity == null) {
            return ApiResponse.prompt(Syscode.APP_VERSION_ID_NOT_EXIST);
        }
        appVersionRepo.delete(id);
        return ApiResponse.prompt(Syscode.SC_OK);
    }


    public Syscode confirmData(AppVersionDto appVersionDto) {
        if (StringUtils.isBlank(appVersionDto.getVersion())) {
            return Syscode.APP_VERSION_VERSION_NOT_NULL;
        }
        if (appVersionDto.getBuild() == null) {
            return Syscode.APP_VERSION_BUILD_NOT_NULL;
        }
        if (StringUtils.isBlank(appVersionDto.getName())) {
            return Syscode.APP_VERSION_NAME_NOT_NULL;
        }
        if (StringUtils.isBlank(appVersionDto.getLink())) {
            return Syscode.APP_VERSION_LINK_NOT_NULL;
        }
        if (StringUtils.isBlank(appVersionDto.getDescription())) {
            return Syscode.APP_VERSION_DESCRIPTION_NOT_NULL;
        }
        return null;
    }


    public Specification<AppVersionEntity> where(SearchAppVersionDto searchAppVersionDto) {
        return (root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (StringUtils.isNotEmpty(searchAppVersionDto.getKeywords())) {
                predicates.add(cb.or(cb.like(root.get("version"), "%" + searchAppVersionDto.getKeywords() + "%")));
            }
            if (StringUtils.isNotEmpty(searchAppVersionDto.getCreateTimeSlot())) {
                String[] date = searchAppVersionDto.getCreateTimeSlot().split("~");

                LocalDate startDate = LocalDate.parse(date[0], DateTimeFormatter.ISO_LOCAL_DATE);
                LocalDate endDate = LocalDate.parse(date[1], DateTimeFormatter.ISO_LOCAL_DATE);
                long startTimestatmp = startDate.atStartOfDay().toInstant(ZoneOffset.of("+8")).getEpochSecond();
                long endTimestatmp = endDate.atStartOfDay().toInstant(ZoneOffset.of("+8")).getEpochSecond();
                predicates.add(cb.and(cb.ge(root.get("createdAt"), startTimestatmp), cb.lt(root.get("createdAt"), endTimestatmp)));
            }
            Predicate[] options = new Predicate[predicates.size()];
            return query.where(predicates.toArray(options)).getRestriction();
        };
    }

}
